/*
 * This file is part of NixNote 
 * Copyright 2009 Randy Baumgarte
 * 
 * This file may be licensed under the terms of of the
 * GNU General Public License Version 2 (the ``GPL'').
 *
 * Software distributed under the License is distributed
 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
 * express or implied. See the GPL for the specific language
 * governing rights and limitations.
 *
 * You should have received a copy of the GPL along with this
 * program. If not, go to http://www.gnu.org/licenses/gpl.html
 * or write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
*/

package com.dream.myqiyi;


import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.lang3.StringEscapeUtils;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Log;
import android.widget.TextView;

import com.evernote.edam.type.Accounting;
import com.evernote.edam.type.PrivilegeLevel;
import com.evernote.edam.type.User;
import com.evernote.edam.type.UserAttributes;
import com.swabunga.spell.engine.Configuration;

import com.dream.myqiyi.config.FileManager;
import com.dream.myqiyi.config.InitializationException;
import com.dream.myqiyi.config.StartupConfig;
import com.dream.myqiyi.dao.NoteResourceModel;
import com.dream.myqiyi.image.util.ImageUtil;
import com.dream.myqiyi.service.ApplicationContext;
import com.dream.myqiyi.service.NoteResourceService;
import com.dream.myqiyi.service.NoteService;
import com.dream.myqiyi.service.NotebookService;
import com.dream.myqiyi.service.TagService;
import com.dream.myqiyi.util.IniReader;
import com.dream.myqiyi.util.Pair;
import com.dream.myqiyi.util.StringUtils;


//*****************************************************
//*****************************************************
//* Global constants & static functions used by 
//* multiple threads.
//*****************************************************
//*****************************************************

public class Global {
	// Set current version and the known versions.
	public static String AppName = "yi_note";
	public static String version = "0.10";
	public static int dbVersion = 1;
	public static String[] validVersions = {"0.10"};
    public static String logfile = "yi_note.log";
    public static final String NOTE_DIR = "yinote";
    public static final String DB_DIR = "db";
    public static final String IMAGE_DIR = "temp" + File.separator + "res";
    public static final String SOUND_DIR = "temp" + File.separator + "res";
    
    public static final boolean IS_REMOTE_DB = true;
    public static final String REMOTE_DB_URL = "jdbc:mysql://211.147.14.120:13306/yinotes";
    public static final String DB_USERNAME = "root";
    public static final String DB_PASSWORD = "yinotes";
    
	//百度地图的key
    public static final String BMAP_KEY = "8C426377B3526B6BF3672C9BA3BB544D1E8289CD";
    
    public static String noteDir = "";
    public static String dbDir = "";
    public static String resDir = "";
    public static String resDirWeb = "";
    
    public static final String SERVER_URL = "http://211.147.14.120:9000/";
    public static final String DEFAULT_USERNAME = "note";
    public static String username = DEFAULT_USERNAME; 
    //public static String password = "";  
    
    public static final int RES_TYPE_UNKNOW = 0;
    public static final int RES_TYPE_IMAGE = 1;
    public static final int RES_TYPE_SOUND = 2;
    
    private static final int TASK_COUNT = 9;  
    private static ExecutorService SINGLE_TASK_EXECUTOR;  
    private static ExecutorService LIMITED_TASK_EXECUTOR;  
    private static ExecutorService FULL_TASK_EXECUTOR;
    static {  
        SINGLE_TASK_EXECUTOR = (ExecutorService) Executors.newSingleThreadExecutor();  
        LIMITED_TASK_EXECUTOR = (ExecutorService) Executors.newFixedThreadPool(7);  
        FULL_TASK_EXECUTOR = (ExecutorService) Executors.newCachedThreadPool();  
    };  
    
    public static AsyncImageLoader asyncImageLoader = new AsyncImageLoader();
    
    public static MyNeverNote myNeverNote;
    
    public static NoteResourceService noteResServ = null;
    public static NoteService noteSrv = null;
    public static NotebookService notebookSrv = null;
    public static TagService tagSrv = null;

    // Each thread has an ID.  This is used primarily to check the status
    // of running threads.
    public static final int mainThreadId=0;
    public static final int syncThreadId=1;
    public static final int tagCounterThreadId=2;
    public static final int trashCounterThreadId=3;   // This should always be the highest thread ID
    public static final int indexThreadId=4;   	// Thread for indexing words
    public static final int saveThreadId=5;   	// Thread used for processing data to saving content
    public static final int notebookCounterThreadId=6;   // Notebook Thread
    public static final int indexThread03Id=7;   // unused
    public static final int indexThread04Id=8;   // unused
    public static final int dbThreadId=9;   // This should always be the highest thread ID
    public static final int threadCount = 10;
    
    
    // These variables deal with where the list of notes appears
    // They will either be vertical (View_List_Narrow) or will be
    // on top of the note (View_List_Wide).  It also has the size of
    // thumbnails displayed in each view
    public static int View_List_Wide = 1;
    public static int View_List_Narrow = 2;
    //public static QSize smallThumbnailSize = new QSize(100,75);
    //public static QSize largeThumbnailSize = new QSize(300,225);

    // This is used to keep a running list of passwords that the user
    // wants us to remember.
    public static HashMap<String,Pair<String,String>> passwordSafe = new HashMap<String, Pair<String,String>>();
    public static List<Pair<String,String>> passwordRemember = new ArrayList<Pair<String,String>>();
    
    
    //public static String currentNotebookGuid;
    
    // These deal with Evernote user settings
    public static User user; 
    public static long authTimeRemaining;
    public static long authRefreshTime;
    public static long failedRefreshes = 0; 
    public static String userStoreUrl;
    public static String noteStoreUrl;
    public static String noteStoreUrlBase;

    // When we want to shut down we set this to true to short
    // circut other threads
    public static boolean keepRunning;
        
    // In the note list, these are the column numbers
    // so I don't need to hard code numbers.
    public static int noteTableCreationPosition = 0;
    public static int noteTableTitlePosition = 1;
    public static int noteTableTagPosition = 2;
    public static int noteTableNotebookPosition = 3;
    public static int noteTableChangedPosition = 4;
    public static int noteTableGuidPosition = 5;
    public static int noteTableAuthorPosition = 6;
    public static int noteTableSourceUrlPosition = 7;
    public static int noteTableSubjectDatePosition = 8;
    public static int noteTableSynchronizedPosition = 9;
    public static int noteTableThumbnailPosition = 10;
    public static int noteTablePinnedPosition = 11;
    public static int noteTableColumnCount = 12;
    public static Integer cryptCounter = 0;
    
    //public static int minimumWordCount = 2;
    
    // Regular expression to parse text with when indexing
    private static String wordRegex;
    
    // Experimental fixes.  Set via Edit/Preferences/Debugging
    public static boolean enableCarriageReturnFix = false;
    public static boolean enableHTMLEntitiesFix = false;
    
    // Used to set & retrieve ini & Windows registry settings
    public static IniReader	settings;     // Set & get ini settings
    public static boolean isConnected;    // Are we connected to Evernote
    public static boolean showDeleted = false;   // Show deleted notes?
    public static boolean disableUploads = false;  // Should we disable uploads (used in testing features)
	public static int messageLevel;   // The level of messages to write to the log files
	public static String tagDelimeter = ",";   // This is used to separate out tag names when entering above note
	public static String attachmentNameDelimeter = "------";  // Used to separate out attachment names in the res directory
	
	
	public static String	appName = new String("myNote");  // database name.  used for multiple databases to separate settings.

	//* Database fields
	public static String	databaseName = new String("main");  // database name.  used for multiple databases to separate settings.
	public static int		databaseVersion = 1;
	public static String	indexDatabaseName = new String("Index"); // searchable words database
	public static int		indexDatabaseVersion = 1;
	public static String	resourceDatabaseName = new String("Resources");  // attachments database
	public static int		resourceDatabaseVersion = 1;
//	public static DateAttributeFilterTable createdSinceFilter;
//	public static DateAttributeFilterTable createdBeforeFilter;
//	public static DateAttributeFilterTable changedSinceFilter;
//	public static DateAttributeFilterTable changedBeforeFilter;
//	public static ContainsAttributeFilterTable containsFilter;
	
	// Log file used for debugging
	//PrintStream stdoutStream;
	
	public static boolean				disableViewing;  // used to disable the editor
	
	// When saving a note, this is a list of things we strip out because Evernote hates them
	public static List<String>				invalidElements = new ArrayList<String>();
	public static HashMap<String, ArrayList<String>> 	invalidAttributes = new HashMap<String, ArrayList<String>>();
	
	public static boolean mimicEvernoteInterface; // Try to mimic Evernote or allow multiple notebook selection
	public static HashMap<String,String> resourceMap;   // List of attachments for a note.
	public static String cipherPassword = "";    // If the database is encrypted, this stores the password
	public static String databaseCache = "16384";  // Default DB cache size
	
	// These are used for performance testing
	static Calendar startTraceTime;   
	static Calendar intervalTraceTime;
	
	static boolean syncOnly;
	
	private static FileManager fileManager;  // Used to access files & directories
	
    // Do initial setup 
    public static void setup(StartupConfig startupConfig) throws InitializationException  {
        try {
			settings = new IniReader(startupConfig.getName());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        disableViewing = startupConfig.getDisableViewing();
        syncOnly = startupConfig.isSyncOnly();

        fileManager = new FileManager(startupConfig.getHomeDirPath(), startupConfig.getProgramDirPath());


		getServer();  // Setup URL to connect to
		
		// Get regular expressions used to parse out words
		String regex = settings.getValue("General", "regex", ", ");
		setWordRegex(regex);
		
		//Setup debugging information
		String msglevel = settings.getValue("Debug", "messageLevel", "Low");
		
		
		//messageLevel = 1;
		setMessageLevel(msglevel);
		keepRunning = true;  // Make sure child threads stay running
		disableUploads = disableUploads();  // Should we upload anything?  Normally true.
		enableCarriageReturnFix = enableCarriageReturnFix();  // Enable test fix?
		enableHTMLEntitiesFix = enableHtmlEntitiesFix();  // Enable test fix?
		
		//shortcutKeys = new ShortcutKeys();  // Setup keyboard shortcuts.
		mimicEvernoteInterface = getMimicEvernoteInterface();  // Should we mimic Evernote's notebook behavior
		resourceMap = new HashMap<String,String>();  // Setup resource map used to store attachments when editing
			
		databaseCache = getDatabaseCacheSize();	 // Set database cache size	
		
		Global.username = getUserInformation().getUsername();
    }
    
    public static String getGuid() {
    	return "{" + UUID.randomUUID().toString() + "}";
    }
    
    public static byte[] getBytesFromFile(File f) {  
    	if (f == null) {  
    		return null;  
    	}  
        
    	try {  
    		FileInputStream stream = new FileInputStream(f);  
    		ByteArrayOutputStream out = new ByteArrayOutputStream(1000);  
          
    		byte[] b = new byte[1000];  
    		int n;  
    		while ((n = stream.read(b)) != -1) {  
    			out.write(b, 0, n);  
    		}  
    		stream.close();  
    		out.close();  
          
    		return out.toByteArray();  
    	} catch (IOException e) {  
    		e.printStackTrace();  
    	}  
        
    	return null;  
    }  
    
    public static File getFileFromBytes(byte[] b, String outputFile) {  
    	BufferedOutputStream stream = null;  
    	File file = null;  
    	try {
    		file = new File(outputFile);
    		FileOutputStream fstream = new FileOutputStream(file);  
    		stream = new BufferedOutputStream(fstream);  
    		stream.write(b);  
    	} catch (Exception e) {  
    		e.printStackTrace();  
    	} finally {  
    		if (stream != null) {  
    			try {  
    				stream.close();  
    			} catch (IOException e) {  
    				e.printStackTrace();  
    			}  
    		}  
    	}  
    	return file;  
    }  

    public static NoteResourceModel getNoteResource(String guid) {
    	// 判断本地有无资源
    	NoteResourceService noteResSrv = (NoteResourceService)ApplicationContext.getSingleton().getBean("NoteResourceService");
    	if (noteResSrv == null) {
    		return null;
    	}
    	NoteResourceModel nr = noteResSrv.getLocalNoteResource(guid);
    	if (nr != null) {
    		File image = new File(Global.resDir + nr.getAttributeFileName());
    		if (!image.exists()) {
    			if (nr.getDataSize() == 0) {
    				return null;
    			} else {
    				getFileFromBytes(nr.getDataBinary(), Global.resDir + nr.getAttributeFileName());
    			}    			
    		}
    		return nr;
    	}
    	
    	nr = noteResSrv.getNoteResource(guid);
    	if (nr != null) {
    		File image = new File(Global.resDir + nr.getAttributeFileName());
    		if (!image.exists()) {
    			if (nr.getDataSize() == 0) {
    				return null;
    			} else {
    				getFileFromBytes(nr.getDataBinary(), Global.resDir + nr.getAttributeFileName());
    			}    			
    		}
    		return nr;
    	}
    	
    	return null;
    }
    
    public static Drawable getImageResource(String guid, int width, int height) {
    	NoteResourceModel nrm = getNoteResource(guid);
    	
    	if (nrm == null) {
    		return null;
    	}
    	
    	if (Global.getResFileType(nrm.getAttributeFileName()) == Global.RES_TYPE_IMAGE) {
    		Bitmap bitmap = ImageUtil.scaleBitmap(Global.resDir + nrm.getAttributeFileName(), width, height);
    		return new BitmapDrawable(bitmap);  
    	} else  {
    		Resources res = BaseApp.instance.getResources();  
    		return res.getDrawable(R.drawable.ic_audio);  
    	}
     }
    
    // Get/Set word parsing regular expression
    public static String getWordRegex() {
    	return wordRegex;
    }
    public static void setWordRegex(String r) {
    	wordRegex = r;
    }

   // Set the debug message level
   public static void setMessageLevel(String msglevel) {
    	if (msglevel.equalsIgnoreCase("low")) 
			messageLevel = 1;
		if (msglevel.equalsIgnoreCase("medium")) 
			messageLevel = 2;
		if (msglevel.equalsIgnoreCase("high")) 
			messageLevel = 3;
		if (msglevel.equalsIgnoreCase("extreme")) 
			messageLevel = 4;
		settings.setValue("Debug", "messageLevel", msglevel);
    }

   //****************************************************
   //****************************************************
   //** Save user account information from Evernote
   //****************************************************
   //****************************************************
    public static void saveUserInformation(User user) {
		settings.setValue("User", "id", String.valueOf(user.getId()));
		settings.setValue("User", "username", user.getUsername());
		settings.setValue("User", "email", user.getEmail());
		settings.setValue("User", "name", user.getName());
		settings.setValue("User", "timezone", user.getTimezone());
		settings.setValue("User", "privilege", String.valueOf(user.getPrivilege().getValue()));
		settings.setValue("User", "created", String.valueOf(user.getCreated()));
		settings.setValue("User", "updated", String.valueOf(user.getUpdated()));
		settings.setValue("User", "deleted", String.valueOf(user.getDeleted()));
		settings.setValue("User", "shard", user.getShardId());
		isPremium();
		if (user.getAttributes()!=null)
			saveUserAttributes(user.getAttributes());
		if (user.getAccounting()!=null)
			saveUserAccounting(user.getAccounting());

    }
    public static User getUserInformation() {
    	User user = new User();
    	//try {	
    		user.setId(Integer.parseInt(settings.getValue("User", "id", String.valueOf(0))));    		
    	//} catch  (java.lang.ClassCastException e) {
    		//user.setId(new Integer(settings.getValue("User", "id", 0)));
    	//}
		String username = (String)settings.getValue("User", "username", "");
		String email = (String)settings.getValue("User", "email", "");
		String name = (String)settings.getValue("User", "name", "");
		String timezone = (String)settings.getValue("User", "timezone", "");
		Integer privilege = 0;
		//try {	
		//	privilege = new Integer((String)settings.getValue("User", "privilege", "0"));			
		//} catch (java.lang.ClassCastException e) {
			privilege = Integer.parseInt(settings.getValue("User", "privilege", String.valueOf(0)));
		//}

		//try {	
			String date = (String)settings.getValue("User", "created", "0");
			user.setCreated(Long.parseLong(date));
			date = (String)settings.getValue("User", "updated", "0");
			user.setUpdated(Long.parseLong(date));
			date = (String)settings.getValue("User", "deleted", "0");
			user.setDeleted(Long.parseLong(date));
//		} catch (java.lang.ClassCastException e) {
//			Long date = (Long)settings.getValue("User", "created", 0);
//			user.setCreated(date);
//			date = (Long)settings.getValue("User", "updated", 0);
//			user.setUpdated(date);
//			date = (Long)settings.getValue("User", "deleted", 0);
//			user.setDeleted(date);
//		}

		String shard = (String)settings.getValue("User", "shard", "");
    	
    	user.setUsername(username);
    	user.setEmail(email);
    	user.setName(name);
    	user.setTimezone(timezone);
    	PrivilegeLevel userLevel = PrivilegeLevel.findByValue(privilege);
    	user.setPrivilege(userLevel);
    	user.setShardId(shard);
    	return user;
    }
    
    public static void saveUserAttributes(UserAttributes attrib) {
		settings.setValue("UserAttributes", "defaultLocationName", attrib.getDefaultLocationName());
		settings.setValue("UserAttributes", "defaultLatitude", attrib.getDefaultLocationName());
		settings.setValue("UserAttributes", "defaultLongitude", attrib.getDefaultLocationName());
		settings.setValue("UserAttributes", "incomingEmailAddress", attrib.getIncomingEmailAddress());
    }
    public static UserAttributes getUserAttributes() {
    	UserAttributes attrib = new UserAttributes();
		attrib.setDefaultLocationName(settings.getValue("UserAttributes", "defaultLocationName",""));
		attrib.setDefaultLatitudeIsSet(false);
		attrib.setDefaultLongitudeIsSet(false);
		attrib.setIncomingEmailAddress(settings.getValue("UserAttributes", "incomingEmailAddress", ""));
		return attrib;
    }
    public static void saveUserAccounting(Accounting acc) {
		settings.setValue("UserAccounting", "uploadLimit", String.valueOf(acc.getUploadLimit()));
		settings.setValue("UserAccounting", "uploadLimitEnd", String.valueOf(acc.getUploadLimitEnd()));
		settings.setValue("UserAccounting", "uploadLimitNextMonth", String.valueOf(acc.getUploadLimitNextMonth()));
		settings.setValue("UserAccounting", "premiumServiceStart", String.valueOf(acc.getPremiumServiceStart()));
		settings.setValue("UserAccounting", "nextPaymentDue", String.valueOf(acc.getNextPaymentDue()));
		settings.setValue("UserAccounting", "uploadAmount", String.valueOf(acc.getUpdated()));
    }
    public static long getUploadLimitEnd() {
    	Long limit;
    	
    	// Upload limit
		try {
			String val  = (String)settings.getValue("UserAccounting", "uploadLimitEnd", "0");
			limit = Long.parseLong(val.trim());
		} catch (Exception e) {
			try {
				limit = Long.parseLong(settings.getValue("UserAccounting", "uploadLimitEnd", "0"));
			} catch (Exception e1) {
				limit = (long) 0;
			}
		}
	
		// return value
    	return limit;
    }
    public static void saveUploadAmount(long amount) {
		settings.setValue("UserAccounting", "uploadAmount", String.valueOf(amount));
   }
    public static long getUploadAmount() {
		long amt=0;
		try {
			String num = (String)settings.getValue("UserAccounting", "uploadAmount", "0");
			amt = Long.parseLong(num.trim());
		} catch (Exception e) {
			try {
				amt = Integer.parseInt(settings.getValue("UserAccounting", "uploadAmount", "0"));
			} catch (Exception e1) {
				amt = 0;
			}
		}
		return amt;
    }
    public static void saveEvernoteUpdateCount(long amount) {
		settings.setValue("UserAccounting", "updateCount", String.valueOf(amount));
    }
    public static long getEvernoteUpdateCount() {
		long amt;
		try {
			String num = (String)settings.getValue("UserAccounting", "updateCount", "0");
			amt = Long.parseLong(num.trim());
		} catch (java.lang.ClassCastException e) {
			amt = 0;
		}
		return amt;
    }
    public static boolean isPremium() {
		int level;
		try {
			String num = (String)settings.getValue("User", "privilege", "1");
			level = Integer.parseInt(num.trim());
		} catch (java.lang.ClassCastException e) {
			try {
				level = Integer.parseInt(settings.getValue("User", "privilege", "1"));
			} catch (Exception e1) {
				level = 1;
			}
		}
		PrivilegeLevel userLevel = PrivilegeLevel.findByValue(level);
		if (userLevel == PrivilegeLevel.NORMAL)
			return false;
		return true;
		
   }
    public static long getUploadLimit() {
		long limit;
		try {
			String num = (String)settings.getValue("UserAccounting", "uploadLimit", "0");
			limit = Long.parseLong(num.trim());
		} catch (java.lang.ClassCastException e) {
			limit = 0;
		}
		return limit;
    }

    
    
    //****************************************************
    //****************************************************
    //** View settings.  Used to restore settings 
    //** when starting and to control how the program
    //** behaves.
    //****************************************************
    //****************************************************
    
    //* Get/Set if we should show a tray icon
    public static boolean showTrayIcon() {
		try {
			String max = (String) settings.getValue("General", "showTrayIcon", "false");
			if (!max.equalsIgnoreCase("true")/* || !QSystemTrayIcon.isSystemTrayAvailable()*/)
				return false;
			else
				return true;   	
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("General", "showTrayIcon", "false"));
			return value;
		}
    }
    public static void setShowTrayIcon(boolean val) {
		if (val)
			settings.setValue("General", "showTrayIcon", "true");
		else
			settings.setValue("General", "showTrayIcon", "false");
    }
    
    // Get/Set window maximized when closed last
    public static boolean wasWindowMaximized() {
    	try {
			String max = (String) settings.getValue("General", "isMaximized", "true");
			if (!max.equalsIgnoreCase("true"))
				return false;
			return true;   	
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("General", "isMaximized", "true"));
			return value;
		}
    }
    public static void saveWindowMaximized(boolean isMax) {
		if (isMax)
			settings.setValue("General", "isMaximized", "true");
		else
			settings.setValue("General", "isMaximized", "false");
    }
    
    // Get/set currently viewed note Guid
    public static String getLastViewedNoteGuid() {
		String guid = (String) settings.getValue("General", "lastViewedNote", "");
		return guid;   	
    }
    public static void saveCurrentNoteGuid(String guid) {
		if (guid != null)
			settings.setValue("General", "lastViewedNote", guid);
		else
			settings.setValue("General", "lastViewedNote", "");
    }
    
    // Get/Set the note column we are sorted on and the order
    public static void setSortColumn(int i) {
    	int view = Global.getListView();
    	if (view == Global.View_List_Wide)
    		settings.setValue("General", "sortColumn", String.valueOf(i));
    	else
    		settings.setValue("General", "sortColumn-Narrow", String.valueOf(i));
    }
    public static int getSortColumn() {;
    String key;
	if (Global.getListView() == Global.View_List_Wide)
		key = "sortColumn";
	else
		key = "sortColumn-Narrow";

	int order;	
	try {
		String val  = settings.getValue("General", key, "0");
		order = Integer.parseInt(val.trim());
	} catch (Exception e) {
		try {
			order = Integer.parseInt(settings.getValue("General", key, "0"));
		} catch (Exception e1) {
		    order = 0;
		}
	}
	return order;
    }
    public static void setSortOrder(int i) {
    	int view = Global.getListView();
    	if (view == Global.View_List_Wide)
    		settings.setValue("General", "sortOrder", String.valueOf(i));
    	else
    		settings.setValue("General", "sortOrder-Narrow", String.valueOf(i));
    }
    public static int getSortOrder() {
    	int view = Global.getListView();
		String key;
    	if (view == Global.View_List_Wide)
    		key = "sortOrder";
   		else
   			key = "sortOrder-Narrow";

		int order;	
		try {
			String val  = settings.getValue("General", key, "0");
			order = Integer.parseInt(val.trim());
		} catch (Exception e) {
			try {
				order = Integer.parseInt(settings.getValue("General", key, "0"));
			} catch (Exception e1) {
			    order = 0;
			}
		}
		return order;
    }
    
    // Should we automatically log in to Evernote when starting?
    public static boolean automaticLogin() {
    	try {
    		String text = (String)settings.getValue("General", "automaticLogin", "false");
    		if (text.equalsIgnoreCase("true"))
    			return true;
    		else
    			return false;		
    	} catch (java.lang.ClassCastException e) {
    		boolean value = Boolean.parseBoolean(settings.getValue("General", "automaticLogin", "false"));
    		return value;
    	}
    }
    public static void setAutomaticLogin(boolean val) {
		if (val)
			settings.setValue("General", "automaticLogin", "true");
		else
			settings.setValue("General", "automaticLogin", "false");
    }

    // Get/set the Evernote server Url.  
    public static void setServer(String server) {
		settings.setValue("General", "server", server);
    }
    public static String getServer() {
		String text = (String)settings.getValue("General", "server", "www.evernote.com");
		if (text.equals("www.evernote.com")) {
			userStoreUrl = "https://www.evernote.com/edam/user";
		    noteStoreUrlBase = "www.evernote.com/edam/note/";	
		} else {
			userStoreUrl = "https://sandbox.evernote.com/edam/user";
			noteStoreUrlBase = "sandbox.evernote.com/edam/note/";
		}
//		if (isPremium())
			noteStoreUrlBase = "https://" + noteStoreUrlBase;
//		else
//			noteStoreUrlBase = "http://" + noteStoreUrlBase;
		return text;
    }

    // Get/Set if we should disable uploads to Evernote
    public static boolean disableUploads() {
    	try {
    		String text = (String)settings.getValue("General", "disableUploads", "false");
    		if (text.equalsIgnoreCase("true"))
    			return true;
    		else
    			return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("General", "disableUploads", "false"));
			return value;
		}
    }
    public static void setDisableUploads(boolean val) {
		if (val)
			settings.setValue("General", "disableUploads", "true");
		else
			settings.setValue("General", "disableUploads", "false");
		disableUploads = val;
    }
 
    // Should we view PDF documents inline?
    public static boolean pdfPreview() {
		try {
			String text = (String)settings.getValue("General", "pdfPreview", "true");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("General", "pdfPreview", "true"));
			return value;
		}
    }
    public static void setPdfPreview(boolean val) {
		if (val)
			settings.setValue("General", "pdfPreview", "true");
		else
			settings.setValue("General", "pdfPreview", "false");
    }
    
    // When creating a new note, should it inherit tags that are currently selected?
    public static boolean newNoteWithSelectedTags() {
		try {
			String text = (String)settings.getValue("General", "newNoteWithSelectedTags", "false");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("General", "newNoteWithSelectedTags", "false"));
			return value;
		}
    }
    public static void setNewNoteWithSelectedTags(boolean val) {
		if (val)
			settings.setValue("General", "newNoteWithSelectedTags", "true");
		else
			settings.setValue("General", "newNoteWithSelectedTags", "false");
    }
    
    // Minimum weight for text OCRed from Evernote. Anything below this
    // Won't be shown to the user when they search
    public static void setRecognitionWeight(int len) {
		settings.setValue("General", "recognitionWeight", String.valueOf(len));
    }
    public static int getRecognitionWeight() {
		Integer len;
		try {
			len = Integer.parseInt(settings.getValue("General", "recognitionWeight", "30"));
		} catch (Exception e) {
			len = 80;
		}
		return len;
    }
    
    // get/set current debug message level
    public static String getMessageLevel() {
		String text = (String)settings.getValue("Debug", "messageLevel", "Low");
		setMessageLevel(text);
		return text;
    }
    public static void setDateFormat(String format) {
		settings.setValue("General", "dateFormat", format);
    }
    
    // Get/Set user date/time formats
    public static String getDateFormat() {
		String text = (String)settings.getValue("General", "dateFormat", "MM/dd/yyyy");
		return text;
    }
    public static void setTimeFormat(String format) {
		settings.setValue("General", "timeFormat", format);
    }
    public static String getTimeFormat() {
		String text = (String)settings.getValue("General", "timeFormat", "HH:mm:ss");
		return text;
    }
    
    // How often should we sync with Evernote?
    public static String getSyncInterval() {
		String text = (String)settings.getValue("General", "syncInterval", "15 minutes");
		return text;    	
    }
    public static void setSyncInterval(String format) {
		settings.setValue("General", "syncInterval", format);
    }
    
    // Get/Set the width of columns and their position for the 
    // next start.
    public static void setColumnWidth(String col, int width) {
    	String section = "";
    	if (Global.getListView() == Global.View_List_Wide)
    		section = "ColumnWidths";
    	else 
    		section = "ColumnWidths-Narrow";
   		settings.setValue(section, col, String.valueOf(width));
   	}
    public static int getColumnWidth(String col) {
    	int view = Global.getListView();
    	String section = "";
    	if (view == Global.View_List_Wide)
    		section = "ColumnWidths";
    	else
    		section = "ColumnWidths-Narrow";
		Integer width;
		try {
			String val  = (String)settings.getValue(section, col, "0");
			width = Integer.parseInt(val.trim());
		} catch (Exception e) {
			try {
				width = Integer.parseInt(settings.getValue(section, col, "0"));
			} catch (Exception e1) {
				width = 0;
			}
		}
		return width;
    }
    public static void setColumnPosition(String col, int width) {
    	String section = "";
    	if (Global.getListView() == Global.View_List_Wide)
    		section = "ColumnPosition";
    	else
    		section = "ColumnPosition-Narrow";
		settings.setValue(section, col, String.valueOf(width));
    }
    public static int getColumnPosition(String col) {
    	String section;
    	if (Global.getListView() == Global.View_List_Wide)
    		section = "ColumnPosition";
    	else
    		section = "ColumnPosition-Narrow";
		int width;
		try {
			String val  = (String)settings.getValue(section, col, "-1");
			width = Integer.parseInt(val.trim());
		} catch (Exception e) {
			try {
				width = Integer.parseInt(settings.getValue(section, col, "0"));
			} catch (Exception e1) {
				width = 0;
			}
		}
		return width;
    }
    
    // Ping the user when they try to delete or just do it.
    public static boolean verifyDelete() {
		try {
			String text = (String)settings.getValue("General", "verifyDelete", "true");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("General", "verifyDelete", "true"));
			return value;
		}
    }
    public static void setVerifyDelete(boolean val) {
		if (val)
			settings.setValue("General", "verifyDelete", "true");
		else
			settings.setValue("General", "verifyDelete", "false");
    }
    
    // Should it start minimized?
    public static boolean startMinimized() {
		try {
			String text = (String)settings.getValue("General", "startMinimized", "false");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("General", "startMinimized", "false"));
			return value;
		}
    }
    public static void setStartMinimized(boolean val) {
		if (val)
			settings.setValue("General", "startMinimized", "true");
		else
			settings.setValue("General", "startMinimized", "false");
    }
    
    // Should we upload the content of any deleted notes
    public static boolean synchronizeDeletedContent() {
		try {
			String text = (String)settings.getValue("General", "syncDeletedContent", "false");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("General", "syncDeletedContent", "false"));
			return value;
		}
    }	
    public static void setSynchronizeDeletedContent(boolean val) {
		if (val)
			settings.setValue("General", "syncDeletedContent", "true");
		else
			settings.setValue("General", "syncDeletedContent", "false");
    }
    
    // Is a section of the window visible?  Used to hide things people don't
    // want to see.
    public static boolean isWindowVisible(String window) {
		try {
			String defaultValue = "true";
			if (window.equalsIgnoreCase("noteInformation"))
				defaultValue = "false";
			String text = (String)settings.getValue("WindowsVisible", window, String.valueOf(defaultValue));
			if (text.equalsIgnoreCase("true"))
				return true;
		else
			return false;		
		} catch (java.lang.ClassCastException e) {
			boolean defaultValue = true;
			if (window.equalsIgnoreCase("noteInformation"))
				defaultValue = false;
			Boolean value = Boolean.parseBoolean(settings.getValue("WindowsVisible", "showTrayIcon", String.valueOf(defaultValue)));
			return value;
		}
    }
    public static void saveWindowVisible(String window, boolean val) {
		if (val)
			settings.setValue("WindowsVisible", window, "true");
		else
			settings.setValue("WindowsVisible", window, "false");
    }
    
    // Is a list in the column in the note list visible?  
    public static boolean isColumnVisible(String window) {
    	String defaultValue = "true";
    	int view = Global.getListView();
    	String section;
    	if (Global.getListView() == Global.View_List_Wide)
    		section = "ColumnsVisible";
    	else
    		section = "ColumnsVisible-Narrow"; 
		if (window.equalsIgnoreCase("thumbnail") && view == Global.View_List_Wide)
			defaultValue = "false";
		if (window.equalsIgnoreCase("thumbnail"))
			defaultValue = "false";
		if (window.equalsIgnoreCase("Guid"))
			defaultValue = "false";
		try {
			String text = (String)settings.getValue(section, window, defaultValue);
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			boolean defBool = false;
			if (window.equalsIgnoreCase("true"))
				defBool = true;
			else
				defBool = false;
			boolean value = Boolean.parseBoolean(settings.getValue(section, window,String.valueOf(defBool)));
			return value;
		}
    }
    public static void saveColumnVisible(String column, boolean val) {
    	String section;
    	if (Global.getListView() == Global.View_List_Wide)
    		section = "ColumnsVisible";
    	else
    		section = "ColumnsVisible-Narrow";    		
		if (val)
			settings.setValue(section, column, "true");
		else
			settings.setValue(section, column, "false");
    }
    
    // Is a particular editor button visible?
    public static boolean isEditorButtonVisible(String window) {
		try {
			String text = (String)settings.getValue("EditorButtonsVisible", window, "true");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("EditorButtonsVisible", window, "true"));
			return value;
		}
    }
    public static void saveEditorButtonsVisible(String column, boolean val) {
		if (val)
			settings.setValue("EditorButtonsVisible", column, "true");
		else
			settings.setValue("EditorButtonsVisible", column, "false");
    }
    
    // Should the test fixes be enabled
    public static boolean enableCarriageReturnFix() {
    	try {
    		String text = (String)settings.getValue("Debug", "enableCarriageReturnFix", "false");
    		if (text.equalsIgnoreCase("true"))
    			return true;
    		else
    			return false;
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("Debug", "enableCarriageReturnFix", "false"));
			return value;
		}
    }
    public static void saveCarriageReturnFix(boolean val) {
		if (val)
			settings.setValue("Debug", "enableCarriageReturnFix", "true");
		else
			settings.setValue("Debug", "enableCarriageReturnFix", "false");
    }
    public static boolean enableHtmlEntitiesFix() {
    	try {
    		String text = (String)settings.getValue("Debug", "enableHtmlEntitiesFix", "false");
    		if (text.equalsIgnoreCase("true"))
    			return true;
    		else
    			return false;
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("Debug", "enableHtmlEntitiesFix", "false"));
			return value;
		}
    }
    public static void saveHtmlEntitiesFix(boolean val) {
		if (val)
			settings.setValue("Debug", "enableHtmlEntitiesFix", "true");
		else
			settings.setValue("Debug", "enableHtmlEntitiesFix", "false");
    }

//    public static void setIndexThreads(int val) {
//		settings.beginGroup("General");
//		settings.setValue("indexThreads", val);
//		settings.endGroup();
//   }
//    public static int getIndexThreads() {
//		settings.beginGroup("General");
//		Integer threads;
//		try {
//			String val  = (String)settings.value("indexThreads", "1");
//			threads = new Integer(val.trim());
//		} catch (Exception e) {
//			try {
//				threads = (Integer)settings.value("indexThreads", 1);
//			} catch (Exception e1) {
//				threads = 1;
//			}
//		}
//		settings.endGroup();
//		threads = 1;
//		return threads;
    
    // Get/Set text zoom factor
//   }
    public static void setZoomFactor(double val) {
		settings.setValue("General", "zoomFactor", String.valueOf(val));
    }
    public static double getZoomFactor() {
		double threads;
		try {
			String val  = (String)settings.getValue("General", "zoomFactor", "1.0");
			threads = Double.parseDouble(val.trim());
		} catch (Exception e) {
			try {
				threads = Double.parseDouble(settings.getValue("General", "zoomFactor", "1.0"));
			} catch (Exception e1) {
				threads = 1;
			}
		}
		return threads;
    }
    public static void setTextSizeMultiplier(double val) {
		settings.setValue("General", "textMultiplier", String.valueOf(val));
    }
    public static double getTextSizeMultiplier() {
		double threads;
		try {
			String val  = (String)settings.getValue("General", "textMultiplier", "1");
			threads = Double.parseDouble(val.trim());
		} catch (Exception e) {
			try {
				threads = Double.parseDouble(settings.getValue("General", "textMultiplier", "1"));
			} catch (Exception e1) {
				threads = 1;
			}
		}
		return threads;
    }
    
    
    // Should we mimic Evernote and restrict the notebooks selected?
    public static boolean getMimicEvernoteInterface() {
		try {
			String text = (String)settings.getValue("General", "mimicEvernoteInterface", "true");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("General", "mimicEvernoteInterface", "true"));
			return value;
		}
    }
    public static void setMimicEvernoteInterface(boolean value) {
    	if (value)
    		settings.setValue("General", "mimicEvernoteInterface", "true");
    	else
    		settings.setValue("General", "mimicEvernoteInterface", "false"); 
    }
    
    
    // Synchronize with Evernote when closing?
    public static boolean synchronizeOnClose() {
		try {
			String text = (String)settings.getValue("General", "synchronizeOnClose", "false");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("General", "synchronizeOnClose", "false"));
			return value;
		}
    }
    public static void setSynchronizeOnClose(boolean val) {
		if (val)
			settings.setValue("General", "synchronizeOnClose", "true");
		else
			settings.setValue("General", "synchronizeOnClose", "false");
    }

    // Get/set the database version.  Not really used any more, but kept
    // for compatibility.
    public static void setDatabaseVersion(String version) {
		settings.setValue("General", "databaseVersion", version);
    }
    public static String getDatabaseVersion() {
		String val  = (String)settings.getValue("General", "databaseVersion", "0.70");
		return val;
    }

    // Get the URL (full path) of the main database
    public static String getDatabaseUrl() {
		String val  = (String)settings.getValue("General", "DatabaseURL", "");
		if (val.equals(""))
			val = "jdbc:h2:"+Global.getFileManager().getDbDirPath(Global.databaseName);
		return val;
    }
    
    // get the url (full path) of the searchable word database
    public static String getIndexDatabaseUrl() {
		String val  = (String)settings.getValue("General", "IndexDatabaseURL", "");
		if (val.equals(""))
			val = "jdbc:h2:"+Global.getFileManager().getDbDirPath(Global.indexDatabaseName);
		return val;
    }
    
    // Get the url (full path) of the attachment database
    public static String getResourceDatabaseUrl() {
		String val  = (String)settings.getValue("General", "ResourceDatabaseURL", "");
		if (val.equals(""))
			val = "jdbc:h2:"+Global.getFileManager().getDbDirPath(Global.resourceDatabaseName);
		return val;
    }
    public static void setDatabaseUrl(String value) {
		settings.setValue("General", "DatabaseURL", value);
    }
    public static void setIndexDatabaseUrl(String value) {
		settings.setValue("General", "IndexDatabaseURL", value);
    }
    public static void setResourceDatabaseUrl(String value) {
		settings.setValue("General", "ResourceDatabaseURL", value);
    }
    public static String getDatabaseUserid() {
		String val  = (String)settings.getValue("General", "databaseUserid", "");
		return val;
    }
    public static String getDatabaseUserPassword() {
		String val  = (String)settings.getValue("General", "databaseUserPassword", "");
		return val;
    }
    
    // get/Set the style sheet and the palette to control the look & feel
    public static void setStyle(String style) {
		settings.setValue("General", "style", style);
    }
    public static String getStyle() {
		String val  = (String)settings.getValue("General", "style", "Cleanlooks");
		return val;
    }
    public static boolean useStandardPalette() {
		try {
			String text = (String)settings.getValue("General", "standardPalette", "true");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("General", "standardPalette", "true"));
			return value;
		}
    }
    public static void setStandardPalette(boolean val) {
		if (val)
			settings.setValue("General", "standardPalette", "true");
		else
			settings.setValue("General", "standardPalette", "false");
    }
    
    // Set the amount of time to wait between indexing
    // Get/Set interval when the index thread wakes up.
    public static void setIndexThreadSleepInterval(int sleep) {
		settings.setValue("General", "IndexThreadSleepInterval", String.valueOf(sleep));
   }
    public static int getIndexThreadSleepInterval() {
		int sleep;
		try {
			String val  = (String)settings.getValue("General", "IndexThreadSleepInterval", "300");
			sleep = Integer.parseInt(val.trim());
		} catch (Exception e) {
			try {
				sleep = Integer.parseInt(settings.getValue("General", "IndexThreadSleepInterval", "0"));
			} catch (Exception e1) {
				sleep = 300;
			}
		}
		return sleep;
    }
    
    
    // Get/Set a window state for later restoring
    public static void saveState(String name, byte[] state) {
    	int view = Global.getListView();
    	if (view == Global.View_List_Narrow)
    		name = name +"Narrow";
		settings.setValue("SaveState", name, String.valueOf(state));
    }
    
    public static byte[] restoreState(String name) {
    	int view = Global.getListView();
    	if (view == Global.View_List_Narrow)
    		name = name +"Narrow";
		return settings.getValue("SaveState", name, "").getBytes();
    }
    public static void saveGeometry(String name, byte[] state) {
    	int view = Global.getListView();
    	String section;
    	if (view == Global.View_List_Narrow)
    		section = "SaveGeometryNarrow";
    	else
    		section = "SaveGeometry";
		settings.setValue(section, name, String.valueOf(state));
    }
    
    public static byte[] restoreGeometry(String name) {
    	int view = Global.getListView();
    	String section;
    	if (view == Global.View_List_Narrow)
    		section = "SaveGeometryNarrow";
    	else
    		section = "SaveGeometry";
		return settings.getValue(section, name, "").getBytes();
    }
    
    
    // Set how often to do an automatic save
    public static void setAutoSaveInterval(int interval) {
		settings.setValue("General", "autoSaveInterval", String.valueOf(interval));
    }
    public static int getAutoSaveInterval() {
		int value;
		try {
			String val  = (String)settings.getValue("General", "autoSaveInterval", "5");
			value = Integer.parseInt(val.trim());
		} catch (Exception e) {
			try {
				value = Integer.parseInt(settings.getValue("General", "autoSaveInterval", "5"));
			} catch (Exception e1) {
				value = 5;
			}
		}
		return value;
    }
     
    // Add an invalid attribute & element to the database so we don't bother parsing it in the future
    // These values we automatically remove from any note.
    // Add invalid attributes
    public static void addInvalidAttribute(String element, String attribute) {
    	
		List<String> attributes = invalidAttributes.get(element);
		if (attributes != null) {
			for (int i=0; i<attributes.size(); i++)
				if (attribute.equalsIgnoreCase(attributes.get(i))) {
					return;
			}
    	}
    	
    	ArrayList<String> attributeList;
    	if (!invalidAttributes.containsKey(element)) {
    		attributeList = new ArrayList<String>();
    		attributeList.add(attribute);
    		invalidAttributes.put(element, attributeList);
    	}
    	else {
    		attributeList = invalidAttributes.get(element);
    		attributeList.add(attribute);
    		invalidAttributes.put(element,attributeList);
    	}
    }
   
    // Add invalid attributes
    public static void addInvalidElement(String element) {
		for (int i=0; i<invalidElements.size(); i++) {
			if (element.equalsIgnoreCase(invalidElements.get(i)))
				return;
		}
    	invalidElements.add(element);
    }
    
    // Get/Set proxy information
    // Proxy settings
    public static String getProxyValue(String key) {
		String val  = (String)settings.getValue("Proxy", key, "");
		return val;
    }
    public static void setProxyValue(String key, String value) {
		settings.setValue("Proxy", key, value);
    }
    
    // Change a byte array to a hex string
    // Convert a byte array to a hex string
	public static String byteArrayToHexString(byte data[]) {
		StringBuffer buf = new StringBuffer();
	    for (byte element : data) {
	    	int halfbyte = (element >>> 4) & 0x0F;
	        int two_halfs = 0;
	        do {
		       	if ((0 <= halfbyte) && (halfbyte <= 9))
		               buf.append((char) ('0' + halfbyte));
		           else
		           	buf.append((char) ('a' + (halfbyte - 10)));
		       	halfbyte = element & 0x0F;
	        } while(two_halfs++ < 1);
	    }
	    return buf.toString();		
	}

    
	// Get/Set spelling settings
	public static boolean getSpellSetting(String value) {
		String text = (String)settings.getValue("Spell", value, "");
		if (text.equalsIgnoreCase("true"))
			return true;
		if (text.equalsIgnoreCase("false"))
			return false;
		if (value.equalsIgnoreCase(Configuration.SPELL_IGNOREDIGITWORDS))
			return true;
		if (value.equalsIgnoreCase(Configuration.SPELL_IGNOREINTERNETADDRESSES))
			return true;
		if (value.equalsIgnoreCase(Configuration.SPELL_IGNOREUPPERCASE))
			return true;
		if (value.equalsIgnoreCase(Configuration.SPELL_IGNORESENTENCECAPITALIZATION))
			return true;
		return false;
    }
    public static void setSpellSetting(String setting, boolean val) {
		if (val)
			settings.setValue("Spell", setting, "true");
		else
			settings.setValue("Spell", setting, "false");
    }
	
	// Get/Set how we should display tags (color them, hide unused, or do nothing)
	// What to do with inactive tags?
	public static String tagBehavior() {
		String text = (String)settings.getValue("General", "tagBehavior", "DoNothing");
		return text;
	}
	// What to do with inactive tags?
	public static void setTagBehavior(String value) {
		settings.setValue("General", "tagBehavior", value);
	}

    
	// Should the toolbar be visible?
	public static boolean isToolbarButtonVisible(String window) {
		try {
			String text = (String)settings.getValue("ToolbarButtonsVisible", window, "true");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;	
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("ToolbarButtonsVisible", window, "true"));
			return value;
		}
    }
    public static void saveToolbarButtonsVisible(String column, boolean val) {
		if (val)
			settings.setValue("ToolbarButtonsVisible", column, "true");
		else
			settings.setValue("ToolbarButtonsVisible", column, "false");
    }
	
    // Are thumbnails enabled?
    
    public static boolean enableThumbnails() {
		try {
			String text = (String)settings.getValue("Debug", "thumbnails", "true");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			boolean value = Boolean.parseBoolean(settings.getValue("Debug", "thumbnails", "true"));
			return value;
		}
    }
    public static void setEnableThumbnails(boolean val) {
		if (val)
			settings.setValue("Debug", "thumbnails", "true");
		else
			settings.setValue("Debug", "thumbnails", "false");
    }
	
    // Trace used for performance tuning.  Not normally used in production.
	// Print date/time.  Used mainly for performance tracing
	public static void trace(boolean resetInterval) {
		String fmt = "MM/dd/yy HH:mm:ss.SSSSSS";
		String dateTimeFormat = new String(fmt);
		SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
		Calendar cal = Calendar.getInstance();
		if (intervalTraceTime == null) 
			intervalTraceTime = Calendar.getInstance();
		if (startTraceTime == null)
			startTraceTime = Calendar.getInstance();
		
		float interval = (cal.getTimeInMillis() - intervalTraceTime.getTimeInMillis());
		float total = (cal.getTimeInMillis() - startTraceTime.getTimeInMillis());
		
//		if (interval > 00.0) {
			StackTraceElement[] exceptions = Thread.currentThread().getStackTrace();
			System.out.println("------------------------------------------");

			System.out.println("Date/Time " +simple.format(cal.getTime()));
			System.out.format("Interval Time: %-10.6f%n", interval);
			System.out.format("Total Time: %-10.6f%n", total);
			for (int i=2; i<5 && i<exceptions.length; i++) {
				System.out.println(exceptions[i]);
			}
//		}
		if (resetInterval)
			intervalTraceTime = cal;
	}
	public static void traceReset() {
		intervalTraceTime = null;
		startTraceTime = null;
	}

    
	// Get the FileManager class to manage local files & directories
	public static FileManager getFileManager() {
        return fileManager;
    }
	
	// Should the note editor be disabled?
    public static boolean getDisableViewing() {
        return disableViewing;
    }

    //**********************
    //* Thumbnail zoom level
    //**********************
    public static int calculateThumbnailZoom(String content) {
    	int zoom = 1;
		if (content.indexOf("application/pdf") == -1) {
			if (content.indexOf("image/") == -1) {
				String text =  StringEscapeUtils.unescapeHtml4(content.replaceAll("\\<.*?\\>", ""));
				zoom = 2;
				if (text.length() < 500) 
					zoom = 2;
				if (text.length() < 250)
					zoom = 3;
				if (text.length() < 100)
					zoom = 4;
				if (text.length() < 50)
					zoom = 5;
				if (text.length() < 10)
					zoom = 6;
			}
		}
		return zoom;
    }
    
    //**********************
    //* List View settings 
    //**********************
    public static void setListView(int view) {
		settings.setValue("General", "listView", String.valueOf(view));
    }
    public static int getListView() {
		Integer value;
		try {
			String val  = (String)settings.getValue("General", "listView", String.valueOf(View_List_Wide));
			value = Integer.parseInt(val.trim());
		} catch (Exception e) {
			try {
				value = Integer.parseInt(settings.getValue("General", "listView", String.valueOf(View_List_Wide)));
			} catch (Exception e1) {
				value = View_List_Wide;
			}
		}
		return value;
    }

    
    
    //*******************
    // Font Settings
    //*******************
    public static boolean overrideDefaultFont() {
		try {
			String text = (String)settings.getValue("Font", "overrideFont", "false");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;	
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("Font", "overrideFont", "false"));
			return value;
		}

    }
    
    //****************************************************
    // Get/Set the default font settings for a new note
    //****************************************************
    public static void setOverrideDefaultFont(boolean value) {
		settings.setValue("Font", "overrideFont", String.valueOf(value));
    }
    public static String getDefaultFont() {
		String val  = (String)settings.getValue("Font", "font", "");
		return val;
    }
    public static void setDefaultFont(String value) {
		settings.setValue("Font", "font", value);
    }
    public static String getDefaultFontSize() {
		String val  = (String)settings.getValue("Font", "fontSize", "");
		return val;
    }
    public static void setDefaultFontSize(String value) {
		settings.setValue("Font", "fontSize", value);
    }
    
    
    //*******************************************
    // Override the close & minimize instead.
    //*******************************************
    public static boolean minimizeOnClose() {
		try {
			String text = (String)settings.getValue("General", "minimizeOnClose", "false");
			if (text.equalsIgnoreCase("true") /*&& QSystemTrayIcon.isSystemTrayAvailable()*/)
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("General", "minimizeOnClose", "false"));
			return value;
		}
    }
    public static void setMinimizeOnClose(boolean value) {
		settings.setValue("General", "minimizeOnClose", String.valueOf(value));
    }

    //*********************************
    // Check version information
    //*********************************
    public static boolean checkVersionUpgrade() {
		try {
			String text = (String)settings.getValue("Upgrade", "checkForUpdates", "true");
			if (text.equalsIgnoreCase("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("Upgrade", "checkForUpdates", "true"));
			return value;
		}
    }
    public static void setCheckVersionUpgrade(boolean value) {
		settings.setValue("Upgrade", "checkForUpdates", String.valueOf(value));
    }
    public static String getUpdatesAvailableUrl() {
		String text = (String)settings.getValue("Upgrade", "avialableUrl", "http://nevernote.sourceforge.net/versions.txt");
		return text;
    }
    public static String getUpdateAnnounceUrl() {
		String text = (String)settings.getValue("Upgrade", "announceUrl", "http://nevernote.sourceforge.net/upgrade.html");
		return text;
    }
    
    //*******************
    // Index settings
    //*******************
    // Set/Get if we should index the text of a note
    public static boolean indexNoteBody() {
		try {
			String value = (String)settings.getValue("Index", "indexNoteBody", "true");
			if (value.equals("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("Index", "indexNoteBody", "true"));
			return value;
		}
    }
    public static void setIndexNoteTitle(boolean value) {
		settings.setValue("Index", "indexNoteTitle", String.valueOf(value));
    }
    // Set/Get if we should index the title of a note
    public static boolean indexNoteTitle() {
		try {
			String value = (String)settings.getValue("Index", "indexNoteTitle", "true");
			if (value.equals("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("Index", "indexNoteTitle", "true"));
			return value;
		}
    }
    public static void setIndexNoteBody(boolean value) {
		settings.setValue("Index", "indexNoteBody", String.valueOf(value));
    }
    // Set/Get if we should index any attachments
    public static boolean indexAttachmentsLocally() {
		try {
			String value = (String)settings.getValue("Index", "indexAttachmentsLocally", "true");
			if (value.equals("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("Index", "indexAttachmentsLocally", "true"));
			return value;
		}
    }
    public static void setIndexImageRecognition(boolean value) {
		settings.setValue("Index", "indexImageRecognition", String.valueOf(value));
    }
    public static boolean indexImageRecognition() {
		try {
			String value = (String)settings.getValue("Index", "indexImageRecognition", "true");
			if (value.equals("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("Index", "indexImageRecognition", "true"));
			return value;
		}
    }
    public static void setIndexAttachmentsLocally(boolean value) {
		settings.setValue("Index", "indexAttachmentsLocally", String.valueOf(value));
    }
    // Get/Set characters that shouldn't be removed from a word
    public static String getSpecialIndexCharacters() {
		String text = (String)settings.getValue("Index", "specialCharacters", "");
		return text;
    }
    public static void setSpecialIndexCharacters(String value) {
		settings.setValue("Index", "specialCharacters", value);	
		databaseCache = value;
    }
    
    //*****************************************************************************
    // Control how tag selection behaves (should they be "and" or "or" selections
    //*****************************************************************************
    public static boolean anyTagSelectionMatch() {
		try {
			String value = (String)settings.getValue("General", "anyTagSelectionMatch", "false");
			if (value.equals("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("General", "anyTagSelectionMatch", "false"));
			return value;
		}
    }
    public static void setAnyTagSelectionMatch(boolean value) {
		settings.setValue("General", "anyTagSelectionMatch", String.valueOf(value));
    }

    //*****************************************************************************
    // Control if a user receives a warning when trying to create a note-to-note link
    // when the DB is not synchronized.
    //*****************************************************************************
    public static boolean bypassSynchronizationWarning() {
		try {
			String value = (String)settings.getValue("User", "bypassSynchronizationWarning", "false");
			if (value.equals("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = (Boolean.parseBoolean(settings.getValue("User", "bypassSynchronizationWarning", "false")));
			return value;
		}
    }
    public static void setBypassSynchronizationWarning(boolean value) {
		settings.setValue("User", "bypassSynchronizationWarning", String.valueOf(value));
    }

    
    //***********************
    //* Database cache size
    //***********************
    public static String getDatabaseCacheSize() {
		String text = (String)settings.getValue("Debug", "databaseCache", "16384");
		return text;
    }
    public static void setDatabaseCache(String value) {
		settings.setValue("Debug", "databaseCache", value);
		databaseCache = value;
    }

    
    // This is used to copy a class since Java's normal deep copy is wacked
    public static Object deepCopy(Object oldObj) 
    {
       ObjectOutputStream oos = null;
       ObjectInputStream ois = null;
       try
       {
          ByteArrayOutputStream bos = 
                new ByteArrayOutputStream(); // A
          oos = new ObjectOutputStream(bos); // B
          // serialize and pass the object
          oos.writeObject(oldObj);   // C
          oos.flush();               // D
          ByteArrayInputStream bin = 
                new ByteArrayInputStream(bos.toByteArray()); // E
          ois = new ObjectInputStream(bin);                  // F
          // return the new object
          return ois.readObject(); // G
       }
       catch(Exception e)
       {
    	   Log.e("[MyNeverNote]", "Exception in ObjectCloner = " + e);
       }
          try {
			oos.close();
	        ois.close();
		} catch (IOException e) {
			Log.e("[MyNeverNote]", "Exception in ObjectCloner = " + e);
			e.printStackTrace();
		}

		return null;
    }

    // If we should automatically select the children of any tag
    public static boolean includeTagChildren() {
		try {
			String value = (String)settings.getValue("General", "includeTagChildren", "false");

			if (value.equals("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("General", "includeTagChildren", "false"));
			return value;
		}

    }
    public static void setIncludeTagChildren(boolean value) {
		settings.setValue("General", "includeTagChildren", String.valueOf(value));
    }
    
    // If we should automatically wildcard searches
    public static boolean automaticWildcardSearches() {
		try {
			String value = (String)settings.getValue("General", "automaticWildcard", "false");
			if (value.equals("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("General", "automaticWildcard", "false"));
			return value;
		}

    }
    public static void setAutomaticWildcardSearches(boolean value) {
		settings.setValue("General", "automaticWildcard", String.valueOf(value));
    }

    // If we should automatically select the children of any tag
    public static boolean displayRightToLeft() {
		try {
			String value = (String)settings.getValue("General", "displayRightToLeft", "false");
			if (value.equals("true"))
				return true;
			else
				return false;
		} catch (java.lang.ClassCastException e) {
			Boolean value = Boolean.parseBoolean(settings.getValue("General", "displayRightToLeft", "false"));
			return value;
		}

    }
    public static void setDisplayRightToLeft(boolean value) {
		settings.setValue("General", "displayRightToLeft", String.valueOf(value));
    }


    //***********************
    //* Startup Notebook
    //***********************
    public static String getStartupNotebook() {
		String text = settings.getValue("General", "startupNotebook", "");
		return text;
    }
    public static void setStartupNotebook(String value) {
		settings.setValue("General", "startupNotebook", value);
		databaseCache = value;
    }
    
    public static String DateFormat(long when, boolean fullFormat) {
    	Time then = new Time();
        then.set(when);
        Time now = new Time();
        now.setToNow();

        // Basic settings for formatDateTime() we want for all cases.
        int format_flags = DateUtils.FORMAT_NO_NOON_MIDNIGHT |
                           DateUtils.FORMAT_ABBREV_ALL |
                           DateUtils.FORMAT_CAP_AMPM;

        // If the message is from a different year, show the date and year.
        if (then.year != now.year) {
            format_flags |= DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE;
        } else if (then.yearDay != now.yearDay) {
            // If it is from a different day than today, show only the date.
            format_flags |= DateUtils.FORMAT_SHOW_DATE;
        } else {
            // Otherwise, if the message is from today, show the time.
            format_flags |= DateUtils.FORMAT_SHOW_TIME;
        }

        // If the caller has asked for full details, make sure to show the date
        // and time no matter what we've determined above (but still make showing
        // the year only happen if it is a different year from today).
        if (fullFormat) {
            format_flags |= (DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME);
        }

        return DateUtils.formatDateTime(BaseApp.context, when, format_flags);
    }
    
    public static String DateMonthFormat(Date d) {
    	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月");
    	return dateFormat.format(d);
    }

    public static boolean isSameMonth(Date d1, Date d2) {
    	if (d1.getYear() == d2.getYear() && d1.getMonth() == d2.getMonth()) {
    		return true;
    	}
    	return false;
    }
    
	public static String getRecorderFileName() {
		return Global.resDir + Global.getGuid() + ".amr";
	}
	
	public static String getPhotoFileName() {
		return Global.resDir + Global.getGuid() + ".jpg";
	}

	public static String getFileNameNoEx(String filename) {
		int start = filename.lastIndexOf(File.separator);
        int end = filename.lastIndexOf(".");

        if (end!=-1) {
        	if (start == -1) {
        		return filename.substring(0,end);
        	} else {
        		return filename.substring(start+1,end);
        	}
        } else {
            return null;
        }
    }
	public static String getFileNameWithEx(String filename) {
		int start = filename.lastIndexOf(File.separator);
        if (start!=-1) {
            return filename.substring(start+1);
        } else {
            return filename;
        }
    }
	public static String getFileExName(String filename) {
        int start = filename.lastIndexOf(".");

        if (start!=-1) {
            return filename.substring(start+1);
        } else {
            return null;
        }
    }
	
	public static int getResFileType(String filename) {
		int ret = RES_TYPE_UNKNOW;
		
		if (StringUtils.isNull(filename)) {
			return RES_TYPE_UNKNOW;
		}

		String ext = getFileExName(filename);
		if (ext.equalsIgnoreCase("png") || ext.equalsIgnoreCase("jpg") || ext.equalsIgnoreCase("jpeg")) {
			ret = RES_TYPE_IMAGE;
		} else if (ext.equalsIgnoreCase("amr")) {
			ret = RES_TYPE_SOUND;
		}
		return ret;
	}

	public static void changeImage(String src, String dst) {
		Bitmap imageBitmap = BitmapFactory.decodeFile(src);
		File f = new File(dst);
		try {
			f.createNewFile();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		FileOutputStream fOut = null;
		try {
			fOut = new FileOutputStream(f);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		imageBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
		try {
            fOut.flush();
		} catch (IOException e) {
            e.printStackTrace();
		}
		try {
            fOut.close();
		} catch (IOException e) {
            e.printStackTrace();
		}
	}

	public static String getExtFromType(String type) {
        int start = type.lastIndexOf("/");

        if (start!=-1) {
            return type.substring(start+1);
        } else {
            return null;
        }
	}

	private static Map<String, String> soundMap = new HashMap<String, String>();
	public static void addSound(String l, String guid) {
		if (!soundMap.containsKey(l)) {
			soundMap.put(l, guid);
		}
			
	}
	
	public static String getSoundGuid(String l) {
		if (!soundMap.containsKey(l)) {
			return null;
		}
		return soundMap.get(l);		
	}

	public static String getDate(long dateTime)  
    {  
        int flags = 0;  
        String date = "";  
          
        if (DateUtils.isToday(dateTime))  
        {  
            flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_24HOUR;  
            date = (String)DateUtils.formatDateTime(BaseApp.context, dateTime, flags);  
        }   
        else  
        {  
            flags = DateUtils.FORMAT_SHOW_DATE;  
            date = (String)DateUtils.formatDateTime(BaseApp.context, dateTime, flags);  
        }  
        return date;  
    }

	private static int index = 0;
	private static Map<String, Integer> resIdxMap = new HashMap<String, Integer>(); 
	public static int getResIndex(String string) {
		if (resIdxMap.containsKey(string)) {
			return resIdxMap.get(string);
		} else {
			int i = ++index;
			resIdxMap.put(string, i);
			return i;
		}
	}
	
	public static void clearResIndex() {
		resIdxMap.clear();
	}
}

